use crate::errors::Result;
use crate::models::User;
use moka::future::Cache;
use std::sync::Arc;
use std::time::Duration;

#[derive(Clone, Debug)]
pub struct AppCache {
    pub user_cache: Arc<Cache<String, User>>,
}

impl AppCache {
    pub fn new(max_capacity: u64, ttl_seconds: u64) -> Self {
        Self {
            user_cache: Arc::new(
                Cache::builder()
                    .max_capacity(max_capacity)
                    .time_to_live(Duration::from_secs(ttl_seconds))
                    .build(),
            ),
        }
    }

    pub async fn get_user(&self, openid: &str) -> Result<Option<User>> {
        Ok(self.user_cache.get(openid).await)
    }

    pub async fn set_user(&self, openid: String, user: User) -> Result<()> {
        self.user_cache.insert(openid, user).await;
        Ok(())
    }

    pub async fn invalidate_user(&self, openid: &str) -> Result<()> {
        self.user_cache.invalidate(openid).await;
        Ok(())
    }

    pub async fn clear_all_users(&self) -> Result<()> {
        self.user_cache.invalidate_all();
        Ok(())
    }
}

impl Default for AppCache {
    fn default() -> Self {
        Self::new(10000, 3600)
    }
}